package com.fightingFish.user.service.impl;

import com.fightingFish.user.bean.Record;
import com.fightingFish.user.bean.User;
import com.fightingFish.user.dao.impl.UserDaoImpl;
import com.fightingFish.user.service.UserService;
import com.fightingFish.util.ConfigUtil;
import com.fightingFish.util.DateUtil;
import net.sf.json.JSONObject;
import org.apache.commons.codec.digest.DigestUtils;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Date;

public class UserServiceImpl implements UserService {

    //创建UserDaoImpl对象
    private UserDaoImpl udi = new UserDaoImpl();

    /**
     * 方法描述：查询User表中该电话号码是否存在
     *
     * @param phone 查询的电话号码
     * @return true ：存在
     * false ：不存在
     */
    @Override
    public boolean queryPhoneFromUser(String phone) {
        //调用dao层queryPhone方法
        return udi.queryPhoneFromUser(phone);
    }

    /**
     * 方法描述：查询temp表中电话号码是否存在
     *
     * @param phone 查询的电话号码
     * @return true ：存在
     * false ：不存在
     */
    @Override
    public boolean queryPhoneFromTemp(String phone) {
        return udi.queryPhoneFromTemp(phone);
    }

    /**
     * 手机号注册获取验证码
     *
     * @param phone 手机号
     * @return
     */
    @Override
    public String phoneRegisterVeriCode(String phone) {
        if (queryPhoneFromUser(phone)) {
            //该手机号已经存在于user表中，说明该用户已经注册过
            return "该手机号已经被注册，可直接进行登录";
        }
        if (queryPhoneFromTemp(phone)) {
            //该手机号已经存在于temp表中，说明该用户已经经由这种方式获取过验证码，则进行修改temp表中的验证码即可
            return smsSend("updateTempVeriCode", phone);
        }
        //该手机号既不存在user表，也不存在temp表，则将手机号和验证码存放在temp表中
        return smsSend("insertTempVeriCode", phone);
    }

    /**
     * 手机号登陆获取验证码
     *
     * @param phone
     * @return
     */
    @Override
    public String phoneLoginVeriCode(String phone) {
        //判断该手机号是否注册
        if (!udi.queryPhoneFromUser(phone)) {
            //未注册
            return "该手机号尚未注册";
        }
        return smsSend("updateUserVeriCode", phone);
    }

    /**
     * 方法描述：发送手机验证码
     *
     * @param mark  访问标识
     * @param phone 手机号
     * @return
     */
    @Override
    public String smsSend(String mark, String phone) {
        //获取随机6位数的验证码（第一位不能为0）
        int veriCode = (int) (Math.random() * 899999) + 100000;
        //编译短信内容
        String smsContent = "【周哥书城】您的验证码为" + veriCode + "，请于10分钟内正确输入，如非本人操作，请忽略此短信。";
        //调用DateUtil工具类的方法获取时间戳
        String timestamp = DateUtil.date2String(new Date(), "yyyyMMddHHmmss");
        //生成签名
        String sig = sign(timestamp);
        //指定返回类型
        String respDataType = "JSON";
        //封装请求参数
        String reqParam = packagReqParam(phone, smsContent, timestamp, sig, respDataType);
        try {
            //将指定格式信息发送给第三方（秒滴）
            //定义变量接收秒滴回复给我们的信息
            String respMessage = send(reqParam);
            //将秒滴响应的信息封装为JSON对象
            JSONObject json = JSONObject.fromObject(respMessage);
            //获取秒滴响应状态码
            String respCode = json.get("respCode").toString();
            //判断响应状态码是否为成功
            if (respCode.equals("00000")) {
                //响应成功，
                Method method = this.getClass().getDeclaredMethod(mark, String.class, String.class);
                String result = (String) method.invoke(this, phone, String.valueOf(veriCode));
                return result;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "验证码发送失败";
    }

    /**
     * 用户手机号注册
     * @param phone
     * @param veriCode
     * @return
     */
    @Override
    public boolean phoneRegister(String phone, String veriCode) {
        return udi.phoneRegister(phone,veriCode);
    }

    /**
     * 手机号登陆
     * @param phone
     * @param veriCode
     * @return
     */
    @Override
    public User phoneLogin(String phone, String veriCode) {
        return udi.phoneLogin(phone,veriCode);
    }

    /**
     * 通过用户ID查询用户个人信息
     */
    @Override
    public User selectInfoByid(Integer userId) {
        return new UserDaoImpl().selectInfoByid(userId);
    }

    /**
     *  用户可以修改个人的基本信息
     * （密码，头像，昵称，性别，个性签名，手机号，邮箱）
     *  返回一个布尔值判断是否修改成功
     */
    @Override
    public boolean updateInfo(Integer userId, String photoImgUrl, String nickName, String sex, String signInfo, String phone, String email) {
        return  new UserDaoImpl().updateInfo(userId,photoImgUrl,nickName,sex,signInfo,phone,email);
    }

    /**
     *  通过用户id找到该用户充值鱼币
     *  返回一个充值后的金额
     */
    @Override
    public Double rechargeBalance(Integer userId, Double investMoney) {
        return new UserDaoImpl().rechargeBalance(userId,investMoney);
    }

    /**
     *  通过用户id找到该用户的消费记录
     */
    @Override
    public ArrayList<Record> selectRecordByid(Integer userId) {
        return new UserDaoImpl().selectRecordByid(userId);
    }

    /**
     * 通过主播id找到该主播收入记录
     *
     * @param AnchorId
     * @return
     */
    @Override
    public ArrayList<Record> selectRecordByAnchorId(Integer AnchorId) {
        return new UserDaoImpl().selectRecordByAnchodId(AnchorId);
//        return null;
    }

    /**
     * 方法概述： 用户购买礼物时 变更余额
     * @param phone
     * @return
     */
    @Override
    public String upDatePrice(String phone ,Double price,int userId,Double balance) {
        Double is = udi.getPrice(phone);
//        判断余额够不够
        if (price>is){
            return "余额不足 无法购买";
        }
//        如果余额充足 返回购买成功 并修改余额
        is-=price;
//        修改余额
        udi.upDatePrice(phone,is);
//    给主播收入余额增加
        balance += price;
        udi.upDateAnchor(balance,userId);
        return "赠送成功";
    }

    /**
     * 用户签到
     * @param userId
     * @return
     */
    @Override
    public boolean signDay(int userId) {
        return udi.signDay(userId);
    }

    /**
     * 修改temp表中的验证码
     *
     * @param phone
     * @param veriCode
     * @return
     */
    public String updateTempVeriCode(String phone, String veriCode) {
        if (udi.updateTempVeriCode(phone, veriCode)) {
            return "验证码发送成功，请注意查收";
        }
        return "验证码发送失败";
    }

    /**
     * 向temp表中添加手机号以及验证码信息
     *
     * @param phone
     * @param veriCode
     * @return
     */
    public String insertTempVeriCode(String phone, String veriCode) {
        if (udi.insertTempVeriCode(phone, veriCode)) {
            return "验证码发送成功，请注意查收";
        }
        return "验证码发送失败";
    }


    /**
     * 修改user表中的验证码信息
     * @param phone
     * @param veriCode
     * @return
     */
    public String updateUserVeriCode(String phone, String veriCode) {
        if (udi.updateUserVeriCode(phone, veriCode))
            return "验证码发送成功，请注意查收";
        return "验证码发送失败";
    }


    /**
     * 方法描述：封装请求参数
     *
     * @param phone        电话号码
     * @param smsContent   短信内容
     * @param timestamp    时间戳
     * @param sig          签名
     * @param respDataType 返回类型
     * @return 封装后的请求参数
     */
    private String packagReqParam(String phone, String smsContent, String timestamp, String sig, String respDataType) {
        StringBuilder sb = new StringBuilder();
        sb.append("accountSid=")
                .append(ConfigUtil.ACCOUNT_SID)
                .append("&smsContent=")
                .append(smsContent)
                .append("&to=")
                .append(phone)
                .append("&timestamp=")
                .append(timestamp)
                .append("&sig=")
                .append(sig)
                .append("&respDataType=")
                .append(respDataType);
        return sb.toString();
    }

    /**
     * 方法描述：根据时间戳以及固定的accountSid和auth_token生成签名
     *
     * @param timestamp 时间戳
     * @return 签名
     */
    private String sign(String timestamp) {
        //1.获取到固定的accountSid和auth_token
        String accountSid = ConfigUtil.ACCOUNT_SID;
        String auth_token = ConfigUtil.AUTH_TOKEN;
        //2.使用MD5加密生成签名
        return DigestUtils.md5Hex(accountSid + auth_token + timestamp);
    }

    /**
     * 方法描述：将指定格式信息发送给第三方（秒滴）
     *
     * @param reqParam 请求参数
     * @return 秒滴回应的信息
     */
    private String send(String reqParam) throws Exception {
        //1.封装请求地址
        URL url = new URL(ConfigUtil.SMS_URL);
        //2.获取连接
        URLConnection urlConnection = url.openConnection();
        //3.设置连接超时时间以及是否可以输入和输出
        urlConnection.setConnectTimeout(10000);
        urlConnection.setDoInput(true);
        urlConnection.setDoOutput(true);
        //4.获取输出流，并转换为字符流，加入缓冲流，并设置字符集编码为UTF-8
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(urlConnection.getOutputStream(), "UTF-8"));
        //5.发送数据给秒滴
        bw.write(reqParam);
        bw.flush();
        //6.获取输入流，并转换为字符流，加入缓冲流，并设置字符集编码为UTF-8
        BufferedReader br = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8"));
        //7.获取秒滴的返回结果
        StringBuffer sb = new StringBuffer();
        String line = "";
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        br.close();
        bw.close();
        return sb.toString();
    }
}
